﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;


namespace Chemistry.Models
{
    /// <summary>
    /// 读卡服务类
    /// </summary>
    public class ReadIdCardService
    {
        #region 声明通用接口
        [DllImport("sdtapi.dll")]
        public static extern int SDT_OpenPort(int iPortID);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ClosePort(int iPortID);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_PowerManagerBegin(int iPortID, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_AddSAMUser(int iPortID, string pcUserName, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_SAMLogin(int iPortID, string pcUserName, string pcPasswd, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_SAMLogout(int iPortID, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_UserManagerOK(int iPortID, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ChangeOwnPwd(int iPortID, string pcOldPasswd, string pcNewPasswd, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ChangeOtherPwd(int iPortID, string pcUserName, string pcNewPasswd, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_DeleteSAMUser(int iPortID, string pcUserName, int iIfOpen);

        [DllImport("sdtapi.dll")]
        public static extern int SDT_StartFindIDCard(int iPortID, ref int pucIIN, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_SelectIDCard(int iPortID, ref int pucSN, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ReadBaseMsg(int iPortID, string pucCHMsg, ref int puiCHMsgLen, string pucPHMsg, ref int puiPHMsgLen, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ReadBaseMsgToFile(int iPortID, string fileName1, ref int puiCHMsgLen, string fileName2, ref int puiPHMsgLen, int iIfOpen);

        [DllImport("sdtapi.dll")]
        public static extern int SDT_WriteAppMsg(int iPortID, ref byte pucSendData, int uiSendLen, ref byte pucRecvData, ref int puiRecvLen, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_WriteAppMsgOK(int iPortID, ref byte pucData, int uiLen, int iIfOpen);

        [DllImport("sdtapi.dll")]
        public static extern int SDT_CancelWriteAppMsg(int iPortID, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ReadNewAppMsg(int iPortID, ref byte pucAppMsg, ref int puiAppMsgLen, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ReadAllAppMsg(int iPortID, ref byte pucAppMsg, ref int puiAppMsgLen, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_UsableAppMsg(int iPortID, ref byte ucByte, int iIfOpen);

        [DllImport("sdtapi.dll")]
        public static extern int SDT_GetUnlockMsg(int iPortID, ref byte strMsg, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_GetSAMID(int iPortID, ref byte StrSAMID, int iIfOpen);

        [DllImport("sdtapi.dll")]
        public static extern int SDT_SetMaxRFByte(int iPortID, byte ucByte, int iIfOpen);
        [DllImport("sdtapi.dll")]
        public static extern int SDT_ResetSAM(int iPortID, int iIfOpen);

        [DllImport("WltRS.dll")]
        public static extern int GetBmp(string file_name, int intf);

        #endregion

        public delegate void De_ReadICCardComplete(IdCard objEDZ);
        public event De_ReadICCardComplete ReadICCardComplete;
        private IdCard objEDZ = new IdCard();
        private int EdziIfOpen = 1; //自动开关串口
        int EdziPortID;

        /// <summary>
        /// 读卡
        /// </summary>
        /// <returns>返回当前身份证</returns>
        public IdCard ReadIDCard()
        {
            bool bUsbPort = false;
            int intOpenPortRtn = 0;
            int rtnTemp = 0;
            int pucIIN = 0;
            int pucSN = 0;
            int puiCHMsgLen = 0;
            int puiPHMsgLen = 0;

            objEDZ = new IdCard();
            //检测usb口的机具连接，必须先检测usb
            for (int iPort = 1001; iPort <= 1016; iPort++)
            {
                intOpenPortRtn = SDT_OpenPort(iPort);
                if (intOpenPortRtn == 144)
                {
                    EdziPortID = iPort;
                    bUsbPort = true;
                    break;
                }
            }
            //检测串口的机具连接
            if (!bUsbPort)
            {
                for (int iPort = 1; iPort <= 2; iPort++)
                {
                    intOpenPortRtn = SDT_OpenPort(iPort);
                    if (intOpenPortRtn == 144)
                    {
                        EdziPortID = iPort;
                        bUsbPort = false;
                        break;
                    }
                }
            }
            if (intOpenPortRtn != 144)
            {
                MessageBox.Show("端口打开失败，请检测相应的端口或者重新连接读卡器！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                return null;
            }
            //在这里，如果您想下一次不用再耗费检查端口的检查的过程，您可以把 EdziPortID 保存下来，可以保存在注册表中，也可以保存在配置文件中，我就不多写了，但是，
            //您要考虑机具连接端口被用户改变的情况哦

            //下面找卡
            rtnTemp = SDT_StartFindIDCard(EdziPortID, ref pucIIN, EdziIfOpen);
            if (rtnTemp != 159)
            {
                rtnTemp = SDT_StartFindIDCard(EdziPortID, ref pucIIN, EdziIfOpen);  //再找卡
                if (rtnTemp != 159)
                {
                    rtnTemp = SDT_ClosePort(EdziPortID);
                    MessageBox.Show("未放卡或者卡未放好，请重新放卡！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return null;
                }
            }
            //选卡
            rtnTemp = SDT_SelectIDCard(EdziPortID, ref pucSN, EdziIfOpen);
            if (rtnTemp != 144)
            {
                rtnTemp = SDT_SelectIDCard(EdziPortID, ref pucSN, EdziIfOpen);  //再选卡
                if (rtnTemp != 144)
                {
                    rtnTemp = SDT_ClosePort(EdziPortID);
                    MessageBox.Show("读卡失败！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return null;
                }
            }
            //注意，在这里，用户必须有应用程序当前目录的读写权限
            FileInfo objFile = new FileInfo("wz.txt");
            if (objFile.Exists)
            {
                objFile.Attributes = FileAttributes.Normal;
                objFile.Delete();
            }
            objFile = new FileInfo("zp.bmp");
            if (objFile.Exists)
            {
                objFile.Attributes = FileAttributes.Normal;
                objFile.Delete();
            }
            objFile = new FileInfo("zp.wlt");
            if (objFile.Exists)
            {
                objFile.Attributes = FileAttributes.Normal;
                objFile.Delete();
            }
            rtnTemp = SDT_ReadBaseMsgToFile(EdziPortID, "wz.txt", ref puiCHMsgLen, "zp.wlt", ref puiPHMsgLen, EdziIfOpen);
            if (rtnTemp != 144)
            {
                rtnTemp = SDT_ClosePort(EdziPortID);
                MessageBox.Show("读卡失败！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                return null;
            }
            //下面解析照片，注意，如果在C盘根目录下没有机具厂商的授权文件Termb.Lic，照片解析将会失败
            if (bUsbPort)
                rtnTemp = GetBmp("zp.wlt", 2);
            else
                rtnTemp = GetBmp("zp.wlt", 1);
            switch (rtnTemp)
            {
                case 0:
                    MessageBox.Show("调用sdtapi.dll错误！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case 1:   //正常
                    break;
                case -1:
                    MessageBox.Show("相片解码错误！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case -2:
                    MessageBox.Show("wlt文件后缀错误！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case -3:
                    MessageBox.Show("wlt文件打开错误！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case -4:
                    MessageBox.Show("wlt文件格式错误！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case -5:
                    MessageBox.Show("软件未授权！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case -6:
                    MessageBox.Show("设备连接错误！", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
            }
            rtnTemp = SDT_ClosePort(EdziPortID);
            FileInfo f = new FileInfo("wz.txt");
            FileStream fs = f.OpenRead();
            byte[] bt = new byte[fs.Length];
            fs.Read(bt, 0, (int)fs.Length);
            fs.Close();

            string str = System.Text.UnicodeEncoding.Unicode.GetString(bt);

            objEDZ.Name = System.Text.UnicodeEncoding.Unicode.GetString(bt, 0, 30).Trim();
            objEDZ.Sex_Code = System.Text.UnicodeEncoding.Unicode.GetString(bt, 30, 2).Trim();
            objEDZ.NATION_Code = System.Text.UnicodeEncoding.Unicode.GetString(bt, 32, 4).Trim();
            string strBird = System.Text.UnicodeEncoding.Unicode.GetString(bt, 36, 16).Trim();
            objEDZ.BIRTH = Convert.ToDateTime(strBird.Substring(0, 4) + "年" + strBird.Substring(4, 2) + "月" + strBird.Substring(6) + "日");
            objEDZ.ADDRESS = System.Text.UnicodeEncoding.Unicode.GetString(bt, 52, 70).Trim();
            objEDZ.IDC = System.Text.UnicodeEncoding.Unicode.GetString(bt, 122, 36).Trim();
            objEDZ.REGORG = System.Text.UnicodeEncoding.Unicode.GetString(bt, 158, 30).Trim();
            string strTem = System.Text.UnicodeEncoding.Unicode.GetString(bt, 188, bt.GetLength(0) - 188).Trim();
            objEDZ.STARTDATE = Convert.ToDateTime(strTem.Substring(0, 4) + "年" + strTem.Substring(4, 2) + "月" + strTem.Substring(6, 2) + "日");
            strTem = strTem.Substring(8);
            if (strTem.Trim() != "长期")
            {
                objEDZ.ENDDATE = Convert.ToDateTime(strTem.Substring(0, 4) + "年" + strTem.Substring(4, 2) + "月" + strTem.Substring(6, 2) + "日");
            }
            else
            {
                objEDZ.ENDDATE = DateTime.MaxValue;
            }
            objFile = new FileInfo("zp.bmp");
            if (objFile.Exists)
            { 
                //Image img = Image.FromFile("zp.bmp");
                //objEDZ.PIC_Image = (Image)img.Clone();
                //System.IO.MemoryStream m = new MemoryStream();
                //img.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg);
                //objEDZ.PIC_Byte = m.ToArray();
                //img.Dispose();
                //img = null;
            }

            //ReadICCardComplete(objEDZ);
            //return true;
            return objEDZ;
        }
    }

    /// <summary>
    /// 身份证类
    /// </summary>
    public class IdCard
    {
        private System.Collections.SortedList nations = new System.Collections.SortedList();
        private string _Name;   //姓名
        private string _Sex_Code;   //性别代码
        private string _Sex_CName;   //性别
        private string _IDC;      //身份证号码
        private string _NATION_Code;   //民族代码
        private string _NATION_CName;   //民族
        private DateTime _BIRTH;     //出生日期
        private string _ADDRESS;    //住址
        private string _REGORG;     //签发机关
        private DateTime _STARTDATE;    //身份证有效起始日期
        private DateTime _ENDDATE;    //身份证有效截至日期
        private string _Period_Of_Validity_Code;   //有效期限代码，许多原来系统上面为了一代证考虑，常常存在这样的字段，二代证中已经没有了
        private string _Period_Of_Validity_CName;   //有效期限
        private byte[] _PIC_Byte;    //照片二进制
        //private Image _PIC_Image;   //照片

        public IdCard()
        {
            nations.Add("01", "汉族");
            nations.Add("02", "蒙古族");
            nations.Add("03", "回族");
            nations.Add("04", "藏族");
            nations.Add("05", "维吾尔族");
            nations.Add("06", "苗族");
            nations.Add("07", "彝族");
            nations.Add("08", "壮族");
            nations.Add("09", "布依族");
            nations.Add("10", "朝鲜族");
            nations.Add("11", "满族");
            nations.Add("12", "侗族");
            nations.Add("13", "瑶族");
            nations.Add("14", "白族");
            nations.Add("15", "土家族");
            nations.Add("16", "哈尼族");
            nations.Add("17", "哈萨克族");
            nations.Add("18", "傣族");
            nations.Add("19", "黎族");
            nations.Add("20", "傈僳族");
            nations.Add("21", "佤族");
            nations.Add("22", "畲族");
            nations.Add("23", "高山族");
            nations.Add("24", "拉祜族");
            nations.Add("25", "水族");
            nations.Add("26", "东乡族");
            nations.Add("27", "纳西族");
            nations.Add("28", "景颇族");
            nations.Add("29", "柯尔克孜族");
            nations.Add("30", "土族");
            nations.Add("31", "达翰尔族");
            nations.Add("32", "仫佬族");
            nations.Add("33", "羌族");
            nations.Add("34", "布朗族");
            nations.Add("35", "撒拉族");
            nations.Add("36", "毛南族");
            nations.Add("37", "仡佬族");
            nations.Add("38", "锡伯族");
            nations.Add("39", "阿昌族");
            nations.Add("40", "普米族");
            nations.Add("41", "塔吉克族");
            nations.Add("42", "怒族");
            nations.Add("43", "乌孜别克族");
            nations.Add("44", "俄罗斯族");
            nations.Add("45", "鄂温克族");
            nations.Add("46", "德昂族");
            nations.Add("47", "保安族");
            nations.Add("48", "裕固族");
            nations.Add("49", "京族");
            nations.Add("50", "塔塔尔族");
            nations.Add("51", "独龙族");
            nations.Add("52", "鄂伦春族");
            nations.Add("53", "赫哲族");
            nations.Add("54", "门巴族");
            nations.Add("55", "珞巴族");
            nations.Add("56", "基诺族");
            nations.Add("57", "其它");
            nations.Add("98", "外国人入籍");
        }
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }
        /// <summary>
        /// 性别代码
        /// </summary>
        public string Sex_Code
        {
            get { return _Sex_Code; }
            set
            {
                _Sex_Code = value;
                switch (value)
                {
                    case "1":
                        Sex_CName = "男";
                        break;
                    case "2":
                        Sex_CName = "女";
                        break;
                }
            }
        }
        /// <summary>
        /// 性别名称
        /// </summary>
        public string Sex_CName
        {
            get { return _Sex_CName; }
            set { _Sex_CName = value; }
        }
        /// <summary>
        /// 身份证号码
        /// </summary>
        public string IDC
        {
            get { return _IDC; }
            set { _IDC = value; }
        }
        /// <summary>
        /// 民族代码
        /// </summary>
        public string NATION_Code
        {
            get { return _NATION_Code; }
            set
            {
                _NATION_Code = value;
                if (nations.Contains(value))
                    NATION_CName = nations[value].ToString();
            }
        }
        /// <summary>
        /// 民族
        /// </summary>
        public string NATION_CName
        {
            get { return _NATION_CName; }
            set { _NATION_CName = value; }
        }
        /// <summary>
        /// 出生日期
        /// </summary>
        public DateTime BIRTH
        {
            get { return _BIRTH; }
            set { _BIRTH = value; }
        }
        /// <summary>
        /// 住址
        /// </summary>
        public string ADDRESS
        {
            get { return _ADDRESS; }
            set { _ADDRESS = value; }
        }
        /// <summary>
        /// 签发机关
        /// </summary>
        public string REGORG
        {
            get { return _REGORG; }
            set { _REGORG = value; }
        }
        /// <summary>
        /// 身份证有效起始日期
        /// </summary>
        public DateTime STARTDATE
        {
            get { return _STARTDATE; }
            set { _STARTDATE = value; }
        }
        /// <summary>
        /// 身份证有效截至日期
        /// </summary>
        public DateTime ENDDATE
        {
            get { return _ENDDATE; }
            set
            {
                _ENDDATE = value;
                if (_ENDDATE == DateTime.MaxValue)
                {
                    _Period_Of_Validity_Code = "3";
                    _Period_Of_Validity_CName = "长期";
                }
                else
                {
                    if (_STARTDATE != DateTime.MinValue)
                    {
                        switch (value.AddDays(1).Year - _STARTDATE.Year)
                        {
                            case 5:
                                _Period_Of_Validity_Code = "4";
                                _Period_Of_Validity_CName = "5年";
                                break;
                            case 10:
                                _Period_Of_Validity_Code = "1";
                                _Period_Of_Validity_CName = "10年";
                                break;
                            case 20:
                                _Period_Of_Validity_Code = "2";
                                _Period_Of_Validity_CName = "20年";
                                break;
                        }
                    }
                }

            }
        }
        /// <summary>
        /// 有效期限代码，许多原来系统上面为了一代证考虑，常常存在这样的字段，二代证中已经没有了
        /// </summary>
        public string Period_Of_Validity_Code
        {
            get { return _Period_Of_Validity_Code; }
            set { _Period_Of_Validity_Code = value; }
        }
        /// <summary>
        /// 一代证有效期限
        /// </summary>
        public string Period_Of_Validity_CName
        {
            get { return _Period_Of_Validity_CName; }
            set { _Period_Of_Validity_CName = value; }
        }
        /// <summary>
        /// 照片二进制
        /// </summary>
        public byte[] PIC_Byte
        {
            get { return _PIC_Byte; }
            set { _PIC_Byte = value; }
        }
        /// <summary>
        /// 照片
        /// </summary>
        //public Image PIC_Image
        //{
        //    get { return _PIC_Image; }
        //    set { _PIC_Image = value; }
        //}
    }
}
